<!-- 文件视图 -->
<template>
  <div class="grid w-screen-calc" ref="fileContainer">
    <!-- 网站 logo -->
    <div class="col-2 text-center">
      <Image style="cursor: pointer;"
             alt="网站图标"
             src="https://img.yeziji.xyz/mobile/logger/forum-mobile.png"
             :width="140"
             @click="() => router.push({ path: '/' })"/>
    </div>
    <!-- 头部用户按钮 -->
    <div class="col-10 align-self-center flex align-items-center"
         style="justify-content: right !important;">
      <UserButton/>
    </div>
    <!-- 筛选条件 -->
    <div class="col-12 grid">
      <span class="col-12 text-center">
        <InputText class="w-5"
                   placeholder="输入相关文件名自动筛选"
                   v-model="filter.filename"/>
      </span>
      <div class="col-12 text-center">
        <div class="m-default-card m-border-radius-none p-2 m-2">
          <h5 id="single">筛选文件类型</h5>
          <SelectButton v-model="filter.ext"
                        :options="exts"
                        aria-labelledby="single"/>
        </div>
      </div>
    </div>
    <!-- 文件列表 -->
    <div class="grid col-12" ref="fileContent">
      <div class="col-12" v-for="(item, index) of filesContent" :key="index">
        <FileItemCard :file-name="item.fileName"
                      :create-date="item.updateTime"
                      :desc="item.desc"
                      :file-size="item.fileSize"
                      :fast-index="index"/>
      </div>
    </div>
    <!-- 上传 -->
    <ToolButton class="upload-tool-btn"
                customer-siderbar-class="upload-siderbar"
                :affix-target-dom="fileContainer"
                :modal="true">
      <template #sidebarContent>
        <FileUploadPanel :url="`${CUSTOMER_FILE}/upload`" path="common" show-input/>
        <!--        <FileUpload :customUpload="true"-->
        <!--                    @uploader="onUploader"-->
        <!--                    @select="onUploadSelect"-->
        <!--                    @remove="onUploadRemove"-->
        <!--                    :multiple="true"-->
        <!--                    :auto="false"-->
        <!--                    :maxFileSize="1073741824">-->
        <!--          <template #header="{chooseCallback, uploadCallback, clearCallback}">-->
        <!--            <div class="flex flex-wrap justify-content-between align-items-center flex-1 gap-2">-->
        <!--              <div class="flex gap-2">-->
        <!--                <Button @click="chooseCallback()"-->
        <!--                        icon="pi pi-upload"-->
        <!--                        class="p-button-rounded"></Button>-->
        <!--                <Button @click="uploadCallback()"-->
        <!--                        :loading="uploadStatus.loading"-->
        <!--                        :disabled="(!uploadStatus.open && !uploadStatus.loading) || renderFiles.length <= 0"-->
        <!--                        icon="pi pi-cloud-upload"-->
        <!--                        class="p-button-rounded p-button-success"></Button>-->
        <!--                <Button @click="clearCallback()"-->
        <!--                        icon="pi pi-times"-->
        <!--                        class="p-button-rounded p-button-danger"></Button>-->
        <!--              </div>-->
        <!--              <InputText class="flex align-items-end flex-wrap justify-content-end" placeholder="上传码"-->
        <!--                         v-model="uploadCode"-->
        <!--                         v-tooltip.top="'不好意思捏，目前只能通过联系管理员来获取上传码哦(~●\'◡\'●)~'"/>-->
        <!--            </div>-->
        <!--          </template>-->
        <!--          <template #content="{files}">-->
        <!--            <div v-if="renderFiles && renderFiles.length > 0">-->
        <!--              <div class="m-file-list">-->
        <!--                <div class="grid" v-for="(file, index) of renderFiles" :key="file.filename">-->
        <!--                  &lt;!&ndash; 文件 svg &ndash;&gt;-->
        <!--                  <div class="col-1 m-file-svg" v-html="file.svg"></div>-->
        <!--                  &lt;!&ndash; 文件信息 &ndash;&gt;-->
        <!--                  <div class="col-10">-->
        <!--                    <div class="grid pl-4">-->
        <!--                      <div class="col-12">-->
        <!--                        {{ file.filename }}-->
        <!--                      </div>-->
        <!--                      <div class="col-12">-->
        <!--                        {{ file.size }}-->
        <!--                        <Badge :value="file.text" :severity="file.color"></Badge>-->
        <!--                      </div>-->
        <!--                    </div>-->
        <!--                  </div>-->
        <!--                  &lt;!&ndash; 上传进度 &ndash;&gt;-->
        <!--                  <div class="col-12">-->
        <!--                    <ProgressBar class="relative" :value="file.progress" :show-value="false"/>-->
        <!--                  </div>-->
        <!--                  &lt;!&ndash; 文件操作按钮 &ndash;&gt;-->
        <!--                  <div class="col-12">-->
        <!--                      <span class="uploader-opera-icon"-->
        <!--                            @click="uploaderOperaHandler({mode: -1, index: index, files: files, file: file })"-->
        <!--                            v-html="CommonSvgJson.upload.delete"></span>-->
        <!--                    <span class="uploader-opera-icon"-->
        <!--                          @click="uploaderOperaHandler({mode: 0, index: index, files: files })"-->
        <!--                          :class="{'m-disabled': !file.open && file.status === -1}"-->
        <!--                          v-html="CommonSvgJson.upload.start"></span>-->
        <!--                    <span class="uploader-opera-icon"-->
        <!--                          @click="uploaderOperaHandler({mode: 1, index: index, file: file.file })"-->
        <!--                          :class="{'m-disabled': file.status !== 1}"-->
        <!--                          v-html="CommonSvgJson.upload.paused"></span>-->
        <!--                  </div>-->
        <!--                  <div class="col-12">-->
        <!--                  </div>-->
        <!--                </div>-->
        <!--              </div>-->
        <!--            </div>-->
        <!--          </template>-->
        <!--          <template #empty>-->
        <!--            <div class="flex align-items-center justify-content-center flex-column" v-if="renderFiles.length === 0">-->
        <!--              <i class="pi pi-upload border-2 border-circle p-5 text-8xl text-400 border-400"/>-->
        <!--              <p class="mt-4 mb-0">拖动或者点击按钮上传文件</p>-->
        <!--            </div>-->
        <!--          </template>-->
        <!--        </FileUpload>-->
      </template>
    </ToolButton>
  </div>
</template>

<script lang="ts" setup>
/** JS */
import {onMounted, reactive, ref, Ref, watch} from 'vue';
import {useRouter} from 'vue-router';
import {FileService, CUSTOMER_FILE} from '@/utils/ApiRequest';
import {FileResponseEntity} from '@/interface/file/entity/FileEntittyInterface';
import Cache from '@/utils/Cache';
/** 组件 */
import FileItemCard from '@/components/card/FileItemCard.vue';
import UserButton from '@/components/button/UserButton.vue';
import FileUploadPanel from '@/components/panel/FileUploadPanel.vue';
import ToolButton from '@/components/button/ToolButton.vue';
import SelectButton from 'primevue/selectbutton';
/** JSON */
import FileExtSvgJson from '@/assets/json/FileExtSvgJson.json';
import FileExtCommonDesc from "@/assets/json/FileExtCommonDesc.json";

const fileService = new FileService(), router = useRouter(), cache = new Cache();
/** 元素钩子 */
const fileContent = ref(null), fileContainer = ref(null);
/** 过滤筛选数据 */
const filter = reactive({
  filename: '',
  ext: '',
  mode: 0,
  open: false
});
/** 后缀数组 */
let exts: string[] = [];

for (let key in FileExtSvgJson) {
  exts.push(key);
}
// 构建后缀
const getExt = (str: string) => {
  let index = str.lastIndexOf('.') + 1;
  let ext = str.substring(index);
  if (FileExtCommonDesc.zips.indexOf(ext) !== -1) {
    return 'zip';
  } else if (FileExtCommonDesc.world.indexOf(ext) !== -1) {
    return 'world';
  } else if (FileExtCommonDesc.excel.indexOf(ext) !== -1) {
    return 'excel';
  } else if (FileExtCommonDesc.process.indexOf(ext) !== -1) {
    return 'process';
  } else if (FileExtCommonDesc.exts.indexOf(ext) === -1) {
    return 'unknown';
  }
  return ext;
}
// 监听后缀筛选操作
const watchExtHandler = (ext: string, reload?: boolean) => {
      // 获取当前的 files 列表
      let fs = reload ? tempFiles.value : filesContent.value;
      // 监听标签选择
      if (ext) {
        filesContent.value = fs.filter(f => {
          let ffn = f.fileName, cext = getExt(ffn);
          if (ext === 'excel' || ext === 'world' || ext === 'zip') {
            // 特殊筛选处理
            return ext === cext;
          }
          // 筛选出后缀相同的文件
          return cext.toLocaleLowerCase() === ext;
        });
        return;
      } else {
        filesContent.value = tempFiles.value;
      }
    },
    // 监听文件名筛选操作
    watchFilenameHandler = (filename: string, reload?: boolean) => {
      let fs = reload ? tempFiles.value : filesContent.value, nlwc = filename.toLocaleLowerCase();
      // 监听 filename 输入
      if (filename && filename.trim() !== '') {
        filesContent.value = fs.filter(f => f.fileName.toLocaleLowerCase().indexOf(nlwc) !== -1);
      } else {
        filesContent.value = tempFiles.value;
      }
    }
// 监听筛选条件的变化
watch(filter, (n) => {
  if (n.filename && n.ext && n.filename.trim() !== '' && n.ext.trim() !== '') {
    // 同时筛选了文件名和后缀名
    watchExtHandler(n.ext);
    watchFilenameHandler(n.filename);
  } else if (n.filename && n.filename.trim() !== '') {
    // 单单筛选文件名
    watchFilenameHandler(n.filename, true);
  } else if (n.ext && n.ext.trim() !== '') {
    // 单单筛选后缀名
    watchExtHandler(n.ext, true);
  } else {
    // 没做任何筛选
    filesContent.value = tempFiles.value;
  }
}, {deep: true});
/** 文件列表加载 */
const filesContent: Ref<FileResponseEntity[]> = ref([]),
    tempFiles: Ref<FileResponseEntity[]> = ref([]);
onMounted(() => {
  // list 目前来说是获取全部数据
  fileService.list().then(data => {
    if (data && data.length > 0) {
      filesContent.value = data;
      tempFiles.value = data;
      filter.open = true;
    }
  })
})
/** 文件上传 */
// const renderFiles: Ref<FileUploadRender[]> = ref([]),
//     uploadStatus = {
//       // 是否允许上传
//       open: false,
//       // 上传按钮加载动画
//       loading: false,
//       // 上传异常锁
//       error: false
//     },
//     uploadCode = ref('');
/*    errorFiles: Ref<any []> = ref([]);

// 上传配置参数
const uploadConfig: UploaderConfig = {
  server: 'http://127.0.0.1:9999/file/upload',
  chunkSize: 1024 << 10,
  threads: 5,
  uploadBeforeSend: async (obj, data, headers) => {
    let defaultData = {
          // 上传目录
          path: 'common',
          // 上传码
          uploadCode: uploadCode.value
        },
        // 获取md5，obj.file[WuFile].source[WuFile#File].source[File]
        md5 = obj.file.source.source.md5;
    headers.Authorization = cache.get('token');
    for (let key in defaultData) {
      data[key] = defaultData[key];
    }
    if (md5) {
      data.md5 = md5;
    }
  },
  uploadAcceptFunction: async (object, ret) => {
    if (ret.code !== 0) {
      toast.error('上传失败', ret.msg, 3000);
      uploadStatus.error = true;
      // 上传失败后，文件会从 WebUploader 中移除。
      console.log('上传失败的文件 = ', object)
      // WebUploader.addFiles 无效
      webUploader.addFiles(object.file.source.source)
      // 加入错误文件队列，用于重新上传
      errorFiles.value.push(object);
    }
  },
  uploadProgressFunction: async (file, progress) => {
    for (let valueElement of renderFiles.value) {
      let valueProgress = valueElement.progress ? valueElement.progress : 0;
      if (file.source.source.md5 === valueElement.md5) {
        if (uploadStatus.error) {
          // 如果错误锁开启，那么直接归 0
          valueElement.progress = 0;
          return;
        }
        if (progress >= valueProgress / 100) {
          valueElement.progress = progress * 100;
        }
      }
    }
  },
  uploadSuccessFunction: async (file, response) => {
    let f = getFileByWU(file);
    if (f) {
      f.progress = 100;
      f.text = '上传完毕';
      f.color = 'danger';
      f.status = 2;
      f.open = false;
    }
  }
}
// 监听错误列表，如果有新增数据则直接回调至 webUploader 当中
watch(() => errorFiles.value, (n) => {
  if (n && n.length > 0) {
    for (let ef of n) {
      console.log('获取错误文件列表重新塞入 webupload 当中 --> ', ef.file.source.source.name);
      webUploader.addFiles(ef.file.source.source);
    }
    errorFiles.value = [];
    console.log('清空错误列表', errorFiles.value);
  }
}, {deep: true});
// 初始化 WebUploader
const webUploader = initUploader(uploadConfig);
// 计算文件 str 大小
const formatSize = (bytes) => {
      if (bytes === 0) {
        return '0 B';
      }
      let k = 1000,
          dm = 3,
          sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
          i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
    },
    // 根据 file 获取 WebUploader#WUFile
    getWUFile = (file) => {
      const files = webUploader.getFiles();
      for (let tmp of files) {
        let md5 = tmp.source.source.md5;
        if (file.md5 === md5) {
          return tmp;
        }
      }
    },
    // 根据 WUFile 获取 File
    getFileByWU = (wuFile) => {
      const files = renderFiles.value;
      for (let tmp of files) {
        let md5 = wuFile.source.source.md5;
        if (tmp.md5 === md5) {
          return tmp;
        }
      }
    },
    // 获取文件后缀
    getExt = (str: string) => {
      let index = str.lastIndexOf('.') + 1;
      let ext = str.substring(index);
      if (FileExtCommonDesc.zips.indexOf(ext) !== -1) {
        return 'zip';
      } else if (FileExtCommonDesc.world.indexOf(ext) !== -1) {
        return 'world';
      } else if (FileExtCommonDesc.excel.indexOf(ext) !== -1) {
        return 'excel';
      } else if (FileExtCommonDesc.process.indexOf(ext) !== -1) {
        return 'process';
      } else if (exts.indexOf(ext) === -1) {
        return 'unknown';
      }
      return ext;
    };

//上传操作
const onUploader = (ev) => {
      // 此处对文件列表进行全部上传
      for (let f of renderFiles.value) {
        webUploader.upload(getWUFile(f.file));
        f.status = 1;
      }
    },
    // 上传文件选择后的操作
    onUploadSelect = (event) => {
      // events#files 是记录当前上传的文件数组
      let files: any[] = event.files;
      for (let tmpFile of files) {
        let currentFile: any = tmpFile;
        // 跳过重复文件
        let arr = renderFiles.value.map(f => {
          return {
            name: f.filename,
            size: f.size
          }
        }).filter(f => f.name === currentFile.name && f.size === formatSize(currentFile.size))
        if (arr.length > 0) continue;
        // 获取文件后缀确认 svg 选择
        let ext = getExt(currentFile.name);
        // 选择文件时计算 md5 值，并加入 webUploader 以及构建渲染文件的数组
        mathMd5(currentFile,
            async (md5, file) => {
              // 记录 MD5 入文件
              currentFile.md5 = md5;
              // 提前判断获取进度是否有问题，如果有问题提前禁止上传
              let res = await fileService.getProcess(md5);
              if (res !== undefined) {
                // 计算 md5 完成后改变状态
                renderFiles.value[file.index].color = 'success';
                renderFiles.value[file.index].text = '等待上传';
                renderFiles.value[file.index].open = true;
                renderFiles.value[file.index].status = 0;
                renderFiles.value[file.index].md5 = md5;
                // 保存进度
                currentFile.currentChunk = res;
                webUploader.addFiles(currentFile);
                // 上传按钮退出 loading
                uploadStatus.loading = false;
              } else {
                toast.error('出问题啦', '可能上传存在某个未发现的问题哦~联系下管理员吧!', 1500);
              }
            },
            (file) => {
              // 动态渲染当前指定文件
              let render: FileUploadRender = {
                svg: FileExtSvgJson[ext] ? FileExtSvgJson[ext] : FileExtSvgJson.unknown,
                filename: currentFile.name,
                size: formatSize(currentFile.size),
                text: '计算 MD5 中',
                color: 'info',
                open: false,
                status: -1,
                file: currentFile
              }
              // 记录下标并加入文件对象属性当中
              file.index = renderFiles.value.length;
              renderFiles.value.push(render);
              // 上传按钮进入 loading
              uploadStatus.loading = true;
            });
      }
    },
    // 文件删除操作
    onUploadRemove = (event) => {
      // console.log('remove ', event);
    }
// 动态渲染文件列表的数据，用于判断是否开放上传
watch(renderFiles, (n) => {
  if (n && n.length > 0) {
    let flag = true;
    for (let f of n) {
      if (!f.open && f.status === 0) {
        // 文件数组中如果等待上传状态且为关闭时禁止上传
        flag = false;
        break;
      }
    }
    uploadStatus.open = flag;
  }
}, {deep: true});
// 按钮操作, -1 删除 | 0 上传 | 1 停止
type UploaderOperaConfig = {
  mode: -1 | 0 | 1
  index: number
  files?: any[]
  file?: any
}
// 小按钮的操作
const uploaderOperaHandler = (config: UploaderOperaConfig) => {
  let mode = config.mode, files = config.files, index = config.index, file = config.file;
  switch (mode) {
    case -1:
      if (files) {
        webUploader.removeFile(getWUFile(file), true);
        files.splice(index, 1);
        renderFiles.value.splice(index, 1);
      } else {
        console.error('获取文件缓存失败');
      }
      break;
    case 0:
      if (file) {
        webUploader.upload(getWUFile(file));
        renderFiles.value[index].status = 1;
      } else {
        console.error('获取文件缓存失败');
      }
      break;
    case 1:
      if (file) {
        webUploader.stop(getWUFile(file));
        renderFiles.value[index].status = 0;
      } else {
        console.error('获取文件缓存失败');
      }
      break;
  }
}*/
</script>

<style lang="less" scoped>
.m-file-list {
  list-style: none;
  padding: 5px !important;

  .m-file-svg {
    height: 60px !important;
    width: 60px !important;
  }
}
</style>
